(function () {
    var baseTemplate = `
        <div class="wrapper">
            <div class="content json_text_content">
                <div class="json_text">
                    <textarea id="JS_JSON_TEXT" placeholder="请输入JSON数据"></textarea>
                    <div class="drag-line" draggable="true"></div>
                </div>
                <div id="js_json_format_result" class="json-result">
                </div>
            </div>
            <div class="controller">
                <button class="commen-btn parse_btn">解析JSON</button>
                <button class="commen-btn close_open_all">全部打开</button>
				<button class="commen-btn parse_js_to_json">解析JS对象至JSON数据</button>
            </div>
        </div>
        <div class="dialog">
            <div class="content">
            </div>
            <div class="btns">
                <button class="close-btn">关闭</button>
            </div>
        </div>
    `;

    var jiantouTemplate = `
    <div class="tree-head">
        <div class="jiantou-wrapper">
            <img class="jt" src="./src/img/jiantou.png" alt="">
        </div>
        <div class="tree-text">
            <span>
                sfionsdfop'k;p[
            </span>
        </div>
    </div>
    `;

    function JsonFormat() { }

    JsonFormat.prototype = {
        init: function (el, options) {
			el = typeof el === 'string' ? document.querySelector(el) : el;
            el.innerHTML = baseTemplate;
            this.autoOpen = options && options.display || 'none';
            this.el = el;
            this.jsonResultDom = this.el.querySelector('#js_json_format_result');
            this.dialog = this.el.querySelector('.dialog');
            this.dialogContent = this.dialog.querySelector('.content');
            this.bindEvent();
        },
        bindEvent: function () {
            var oParseBtn = this.el.querySelector('.parse_btn'),
                oCloseOpenAllLevel = this.el.querySelector('.close_open_all'),
                closeDialogBtn = document.querySelector('.close-btn'),
				parseJsToJson = document.querySelector('.parse_js_to_json'),
                _this = this;
			
			parseJsToJson.addEventListener('click',function(e){
				var oJsonText = _this.el.querySelector('#JS_JSON_TEXT').value;
				if(oJsonText){
					const obj = new Function('return' + oJsonText)();
					_this.el.querySelector('#JS_JSON_TEXT').value = JSON.stringify(obj);
					oParseBtn.click();
				}
			})

            closeDialogBtn.addEventListener('click', function (e) {
                _this.dialog.style.display = 'none';
            }, false);

            oCloseOpenAllLevel.addEventListener('click', function (e) {
                _this.autoOpen = _this.autoOpen === 'block' ? 'none' : 'block';
                if (_this.autoOpen === 'block') {
                    oCloseOpenAllLevel.innerHTML = '全部关闭';
                } else {
                    oCloseOpenAllLevel.innerHTML = '全部打开';
                }
                var oJsonText = _this.el.querySelector('#JS_JSON_TEXT').value;
                if (oJsonText) {
                    _this.JsonObject = _this._parseJson(oJsonText)
                    if (_this.JsonObject) {
                        _this.jsonResultDom.innerHTML = '';
                        _this.jsonResultDom.appendChild(_this._genTree(_this.JsonObject));
                        _this.treeBindEvent();
                    }
                } else {
                    _this._showDialog('JSON数据字符串为空，请检查后重新输入');
                }
            }, false);

            oParseBtn.addEventListener('click', function (e) {
                var oJsonText = _this.el.querySelector('#JS_JSON_TEXT').value;
                if (oJsonText) {
                    _this.JsonObject = _this._parseJson(oJsonText)
                    if (_this.JsonObject) {
                        _this.el.querySelector('#JS_JSON_TEXT').value = _this.prettyFormat(oJsonText);
                        _this.jsonResultDom.innerHTML = '';
                        _this.jsonResultDom.appendChild(_this._genTree(_this.JsonObject));
                        _this.treeBindEvent();
                    }
                } else {
                    _this._showDialog('JSON数据字符串为空，请检查后重新输入');
                }
            }, false);
            this._dragCenterLine()
        },
        _dragCenterLine(){
            const oDragLine = document.querySelector('.drag-line'),
                  oJsonText = document.querySelector('.json_text');
            oDragLine.addEventListener('mouseenter', function(){
                oDragLine.style.backgroundColor = '#999';
            }, false)


            oDragLine.addEventListener('mouseout', function(){
                oDragLine.style.backgroundColor = 'transparent';
            }, false)

            oDragLine.addEventListener('drag', function(ev){
                if(ev.clientX <= 200){
                    oDragLine.style.left = '200px';
                    oJsonText.style.width = '200px';
                }else if(ev.clientX >= window.innerWidth - 200){
                    oDragLine.style.left = window.innerWidth - 200 + 'px';
                    oJsonText.style.width = window.innerWidth - 200 + 'px';
                } else{
                    oDragLine.style.left = ev.clientX + 'px';
                    oJsonText.style.width = parseInt(oDragLine.style.left) + 'px';
                }
                oDragLine.style.backgroundColor = '#999';
            }, false)
            oDragLine.addEventListener('dragend', function(ev){
                if(ev.clientX <= 200){
                    oDragLine.style.left = '200px';
                    oJsonText.style.width = '200px';
                }else if(ev.clientX >= window.innerWidth - 200){
                    oDragLine.style.left = window.innerWidth - 200 + 'px';
                    oJsonText.style.width = window.innerWidth - 200 + 'px';
                } else{
                    oDragLine.style.left = ev.clientX + 'px';
                    oJsonText.style.width = parseInt(oDragLine.style.left) + 'px';
                }
                oDragLine.style.backgroundColor = 'transparent';
            }, false)
        },
        prettyFormat(str) {
            try {
                // 设置缩进为2个空格
                str = JSON.stringify(JSON.parse(str), null, 2);
                str = str
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;');
                return str.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
                    var cls = 'number';
                    if (/^"/.test(match)) {
                        if (/:$/.test(match)) {
                            cls = 'key';
                        } else {
                            cls = 'string';
                        }
                    } else if (/true|false/.test(match)) {
                        cls = 'boolean';
                    } else if (/null/.test(match)) {
                        cls = 'null';
                    }
                    return match;
                });
            } catch (e) {
                alert("异常信息:" + e);
            }


        },
        _genTree: function (jsonObject) {
            var keys = Object.keys(jsonObject),
                _this = this,
                _treeWarpper = document.createElement('div'),
                is = false,
                _childs = null;//一会有用 所以声明的作用域大一些
            _treeWarpper.className = 'tree-wrapper';

            // 只创建一次 第一次 其他的都放置在这个容器里面
            if (!is) {
                var _tree = document.createElement('div');
                _tree.innerHTML = jiantouTemplate;
                _tree.className = 'tree child';
                // 默认不可见
                _childs = document.createElement('div');
                _childs.className = 'childs';
                _childs.style.display = _this.autoOpen;
                _tree.querySelector('span').innerHTML = _this._getType(jsonObject).toLowerCase();
                _tree.appendChild(_childs);
                _treeWarpper.appendChild(_tree);
                is = !is;
            }

            keys.forEach(function (item, index, arr) {
                switch (_this._getType(jsonObject[item])) {
                    case 'object':
                        _this._genObjectAndArray(jsonObject[item], _childs, item)
                        break;
                    case 'array':
                        _this._genObjectAndArray(jsonObject[item], _childs, item)
                        break;
                    default:
                        var _oTreeItem = document.createElement('div');
                        _oTreeItem.className = 'tree-item';
                        _oTreeItem.innerHTML = `<span style="color:#204a87;cursor: pointer;">${item}</span> : <span style="color:#4e9a06;cursor: pointer;">${jsonObject[item]}</span>`;
                        _childs.appendChild(_oTreeItem);
                        break;
                }
            })
            return _treeWarpper;
        },
        /**
         * 对象和数组级别的DOM生成
         * @param {*} data 
         * @param {*} dom 
         */
        _genObjectAndArray(data, dom, keyName) {
            var oTreeChild = document.createElement('div'),
                oChilds = document.createElement('div');
            oTreeChild.className = 'tree-child';
            oTreeChild.innerHTML = jiantouTemplate;
            oTreeChild.querySelector('span').innerHTML = `${keyName}----${this._getType(data).toLowerCase()}`;
            oChilds.className = 'childs';
            oChilds.style.display = this.autoOpen;
            oTreeChild.appendChild(oChilds);
            var keys = Object.keys(data);
            keys.forEach((item, index, arr) => {
                switch (this._getType(data[item])) {
                    case 'object':
                        this._genObjectAndArray(data[item], oChilds, item);
                        break;
                    case 'array':
                        this._genObjectAndArray(data[item], oChilds, item);
                        break;
                    default:
                        var _oTreeItem = document.createElement('div');
                        _oTreeItem.className = 'tree-item';
                        _oTreeItem.innerHTML = `<span style="color:#204a87;cursor: pointer;">${item}</span> : <span style="color:#4e9a06;cursor: pointer;">${data[item]}</span>`;
                        oChilds.appendChild(_oTreeItem);
                        break;
                }
            })
            dom.appendChild(oTreeChild);
        },
        treeBindEvent: function () {
            var oTreeWarpper = document.getElementsByClassName('tree-wrapper')[0];
            oTreeWarpper.addEventListener('click', function (e) {
                var constClassName = 'tree-head',
                    tar = e.target || e.srcElement;
                if (tar.parentNode.parentNode.className === constClassName) {
                    var oChilds = tar.parentNode.parentNode.parentNode.getElementsByClassName('childs')[0];
                    if (oChilds.style.display === 'block') {
                        oChilds.style.display = 'none';
                        tar.parentNode.parentNode.getElementsByClassName('jt')[0].className = 'jt';
                    } else {
                        oChilds.style.display = 'block';
                        tar.parentNode.parentNode.getElementsByClassName('jt')[0].className = 'jt active';
                    }
                }
            }, false);
        },
        _showDialog(msg) {
            this.dialogContent.innerHTML = msg;
            this.dialog.style.display = 'block';
        },
        /**
         * 解析JSON数据
         * @param {*} text string
         * @returns 
         */
        _parseJson: function (text) {
            var res = null;
            try {
                res = JSON.parse(text);
            } catch (e) {
                this._showDialog(e);
                return res;
            }
            return res;
        },
        /**
         * 显示错误信息
         * 
         * @param {*} msg string
         */
        _parseError: function (msg) {
            var oP = document.createElement('p');
            oP.innerHTML = msg;
            oP.style.color = 'red';
            oP.style.fontSize = '22px';
            oP.style.width = '100%';
            oP.style.height = '50px';
            oP.style.lineHeight = '50px';
            this.jsonResultDom.innerHTML = '';
            this.jsonResultDom.appendChild(oP);
        },
        _getType: function (val) {
            var toStr = Object.prototype.toString;
            switch (toStr.call(val)) {
                case '[object Array]':
                    return 'array';
                    break;
                case '[object Object]':
                    return 'object';
                    break;
                case '[object String]':
                    return 'string';
                    break;
                case '[object Number]':
                    return 'number';
                    break;
                case '[object Null]':
                    return 'null';
                    break;
                case '[object Boolean]':
                    return 'boolean';
                    break;
            }
        }
    }

    window.JsonFormat = JsonFormat;
})()